<?php

// @formatter:off
/**
 * @file WCTranslate.php
 *
 * @author Alejandro Dario Simi
 * @date $Date: 2014-05-04 01:33:52 +0000 (Sun, 04 May 2014) $
 *
 * $Id: WCTranslate.php 111 2014-05-04 01:33:52Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/includes/lang/WCTranslate.php $
 */
// @formatter:on


/**
 * @class WCTranslate 
 */
class WCTranslate extends WCSingleton {
	//
	// Class constants.
	const JSPrefix = "translates.";
	//
	// Protected class properties.
	protected static $_TranslateParameter = "WCTranslate_config";
	//
	// Protected properties.
	protected $_config = false;
	protected $_configSerialized = false;
	/**
	 * @var string[string][]
	 */
	protected $_keywords = array(
		"search" => array(),
		"replacement" => array()
	);
	/**
	 *
	 * @var WCLangTranslationHolder
	 */
	protected $_holder = false;
	//
	// Magic methods.
	public function __destruct() {
		$this->saveConfig();
	}
	//
	// Public methods.
	public function config() {
		return $this->_config;
	}
	public function isConfigChanged() {
		$auxConf = serialize($this->_config);
		return ($auxConf != $this->_configSerialized);
	}
	public function lang($alias = false) {
		$out = false;

		if(!isset($_REQUEST["wclang"])) {
			global $wcDefaults;
			$out = $wcDefaults["language"];
		} else {
			$out = $_REQUEST["wclang"];
		}

		if(!$alias && isset($this->_config->aliases[$out])) {
			$out = $this->_config->aliases[$out];
		}

		return $out;
	}
	public function langs() {
		return array_unique(array_values($this->_config->aliases));
	}
	public function setDefault($default = "en_us") {
		$this->_config->default = $default;
	}
	public function setReplacement($search, $replacement) {
		$key = "{@".strtoupper($search)."}";
		$this->_keywords["search"][] = $key;
		$this->_keywords["replacement"][] = $replacement;
	}
	public function translate($name, $keywords = false) {
		return $this->translateFor($this->lang(true), $name, $keywords);
	}
	public function translateFor($keyword, $name, $keywords = false) {
		$out = "@{$name}";

		if(!isset($_REQUEST["nolang"])) {
			if(isset($this->_config->aliases[$keyword])) {
				$keyword = $this->_config->aliases[$keyword];
			}

			$items = $this->_holder->itemByNameInKeyword($name, $keyword);
			$item = array_shift($items);
			if($item && $item->ok()) {
				$out = $item->translation;
				if($keyword === false) {
					$out = str_replace($this->_keywords["search"], $this->_keywords["replacement"], $out);
				} else {
					$out = str_replace($keywords["search"], $keywords["replacement"], $out);
				}
			}
		} else {
			$out = "<span class='nolang'>@{$name}</span>";
		}

		return $out;
	}
	public function update($isCron = false, $spacer = "") {
		if($isCron) {
			global $wcDefaults;
			echo "{$spacer}Default Language: ".WCColorText::ShellGreen($wcDefaults["language"])."\n";
			echo "{$spacer}Loading XML list:\n";
		}
		$this->loadLangXMLList($isCron, "{$spacer}\t");

		if($this->isConfigChanged()) {
			if($isCron) {
				echo "{$spacer}Rebuilding translation index:\n";
			}
			$this->rebuildIndex($isCron, "{$spacer}\t");
			$this->saveConfig();
		}
//@TODO DEBUG SACAR ESTO
		$this->generateJSCache($isCron, $spacer);
//@TODO DEBUG SACAR ESTO
	}
	//
	// Protected methods.
	protected function generateJSCache($isCron, $spacer) {
		global $wcPaths;

		if($isCron) {
			echo "{$spacer}Removing old JS files:\n";
		}
		$langs = array_unique(array_values($this->_config->aliases));
		$prefix = "{$wcPaths["cache-directory"]}/{$wcPaths["cache-js-uri"]}/".self::JSPrefix;
		foreach($langs as $lang) {
			$path = "{$prefix}{$lang}.js";
			if($isCron) {
				echo "{$spacer}\tRemoving '{$path}' [{$lang}]: ";
			}
			if(is_file($path)) {
				@unlink($path);
				if(is_file($path) && $isCron) {
					echo WCColorText::ShellRed("Failed\n");
				} elseif($isCron) {
					echo WCColorText::ShellGreen("Done\n");
				}
			} elseif($isCron) {
				echo WCColorText::ShellYellow("Ignored\n");
			}
		}

		foreach($langs as $lang) {
			$jsContents = "/*\n";
			$jsContents.= " * This is an autogenerated file, do not modify.\n";
			$jsContents.= " */\n\n";
			$path = "{$prefix}{$lang}.js";
			if($isCron) {
				echo "{$spacer}\tGenerating '{$path}' [{$lang}]: ";
			}

			foreach($this->_holder->itemByKeyword($lang) as $item) {
				$jsContents.= "wcomix.lang._translations.{$item->name} = \"{$item->translation}\";\n";
			}

			file_put_contents($path, $jsContents);
			if($isCron) {
				echo WCColorText::ShellGreen("Done\n");
			}
		}
	}
	protected function init() {
		$this->_holder = WCLangTranslationHolder::I();
		$this->loadConfig();
	}
	protected function checkConfig() {
		$update = false;

		global $wcDefaults;

		if(!$this->_config) {
			$this->_config = new stdClass();
			$update = true;
		}
		if(!isset($this->_config->default) || $this->_config->default != $wcDefaults["language"]) {
			$this->_config->default = $wcDefaults["language"];
			$update = true;
		}

		if(!isset($this->_config->aliases)) {
			$this->_config->aliases = array();
			$update = true;
		}
		if(!isset($this->_config->langs)) {
			$this->_config->langs = array();
			$update = true;
		}

		if($update) {
			$this->saveConfig();
		}
	}
	protected function loadConfig() {
		eval("\$this->_configSerialized = WCParameters::I()->".self::$_TranslateParameter.";");

		if(!$this->_configSerialized) {
			$this->checkConfig();
		} else {
			$this->_configSerialized = gzuncompress($this->_configSerialized);
			$this->_config = unserialize($this->_configSerialized);
			$this->checkConfig();
		}
	}
	protected function loadLangXMLList($isCron, $spacer) {
		$this->_config->langs = array();

		global $wcLanguageFolders;
		foreach($wcLanguageFolders as $path) {
			$directory = new RecursiveDirectoryIterator($path);
			$iterator = new RecursiveIteratorIterator($directory);
			$regex = new RegexIterator($iterator, '/([a-z0-9_-]*)\/lang\.xml$/', RecursiveRegexIterator::GET_MATCH);
			foreach($regex as $filename => $data) {
				$this->_config->langs[] = array(
					"filename" => $filename,
					"lang" => $data[1],
					"stat" => stat($filename)
				);
			}
		}

		if($isCron) {
			foreach($this->_config->langs as $xml) {
				echo "{$spacer}[{$xml["lang"]}] '{$xml["filename"]}'\n";
			}
		}
	}
	protected function rebuildIndex($isCron, $spacer) {
		if($isCron) {
			echo "{$spacer}Destroying current data: ";
		}
		$this->_holder->rebuild();
		if($isCron) {
			echo WCColorText::ShellGreen("Done\n");
			echo "{$spacer}Loading XMLs:\n";
		}

		$this->_config->aliases = array();

		foreach($this->_config->langs as $lang) {
			if($isCron) {
				echo "{$spacer}\t\tLoading '{$lang["filename"]}' [{$lang["lang"]}]: \n";
			}

			if(self::Validate($lang["filename"])) {
				$xml = new SimpleXMLElement(file_get_contents($lang["filename"]));

				$countAliases = 0;
				$countTranslations = 0;

				if(isset($xml->alias)) {
					foreach($xml->alias as $alias) {
						$countAliases++;
						$this->_config->aliases[(string)$alias] = $lang["lang"];
					}
				}

				$keyword = $lang["lang"];
				foreach($xml->translation as $translation) {
					$countTranslations++;
					$items = $this->_holder->itemByNameInKeyword((string)$translation->name, $keyword);
					if(!$items) {
						$item = $this->_holder->createInKeyword((string)$translation->name, $keyword);
					} else {
						$item = array_shift($items);
					}

					if($item && $item->ok()) {
						$item->translation = (string)$translation->value;
					} else {
						echo WCColorText::ShellRed("{$spacer}\t\tUnable to create translation for '{$translation->name}'\n");
					}
				}

				if($isCron) {
					echo "{$spacer}\t\t\tAliases:     {$countAliases}\n";
					echo "{$spacer}\t\t\tTranslations: {$countTranslations}\n";
				}

				$this->generateJSCache($isCron, $spacer);
			} else {
				if($isCron) {
					echo WCColorText::ShellRed("{$spacer}\t\t\tXML '{$lang["lang"]}' is not valid\n");
				}
			}
		}
	}
	protected function saveConfig() {
		if($this->isConfigChanged()) {
			$auxConf = gzcompress(serialize($this->_config));
			eval("WCParameters::I()->".self::$_TranslateParameter." = \$auxConf;");
		}
	}
	//
	// Public class methods.
	public static function Validate($path, &$eror = null) {
		//
		// Setting the default value to be returned.
		$ok = false;
		//
		// Checking if the file exists and it's readable.
		if(is_readable($path)) {
			//
			// Creating a DOM as XML checker.
			$dom = new DOMDocument;
			//
			// Loading file into the DOM checker object.
			$dom->Load($path);
			//
			// Checking its validity.
			$ok = @$dom->validate();
			//
			// Clearing DOM checker object.
			unset($dom);
		}
		//
		// Returning results.
		return $ok;
	}
}
